#include "globalvar.h"
#define INSIDETOKEN *p!=' '&&*p!='\n'&&*p!='\t'&&*p!='\0'&&*p!=')'&&*p!='('
#define WAITPAIR(x,add)         \
      while(*p!='\0'&&*p!=x){   \
        if(*p=='\\'&&p[1]!='\0')\
          add;                  \
	      add;                    \
      }

//从p 开始找到np个括号内本项结束位置返回
//若np=0本项为空则吞1个括号，np=-1
char* getNextPos(char* p,char* np){
  char tmp=0;
  if(!np)np=&tmp;
  do{
    char stat=1;
    while(stat)
      switch(*p){
      case '\0':return p;
      case '(':(*np)+=2;
      case ')':(*np)-=1;if(*np<1){
          return p+1;
        }
      case ' ':case '\n':case '\t':++p;break;//去空格
      default:stat=0;
      }
    while(*p>='0'&&*p<='9')++p;
    //判断引号是否存在
    switch(*p){
    case '\'':
      if(*(++p)=='('){++(*np);++p;}//有引号且（ 
      else {//有引号无（
        WAITPAIR('\'',p++);
        if(*p!='\0')++p;
      }
      break;
    default://没有引号
      if(*p=='\"'){
        p++;
        WAITPAIR('\"',p++);
        if(*p!='\0')p++;
      }else{
        while(INSIDETOKEN)
          p++;
      }
    }
  }while(*np>0);
  return p;
}

//规范格式输出一项
//输入 {----, a.w, a.t, a.Q, a.tag}
//输出 {----, a.w, ---, ---, -----}
At putToken(At a){
  char *p=a.w;
  switch(a.tag){
  case ISLP:   sprintf(p,"(");break;
  case ISRP:   sprintf(p,") ");break;
  case ISNULL:        *p='\0';break;
  case ISTOKEN:
    switch(a.Q){
    case  1:  sprintf(p,"\'%s\' ",a.t);break;
    case  0:  if(*a.t)sprintf(p,"%s ",a.t);
              else    *p=0;
              break;
    default:  sprintf(p,"%d'%s' ",a.Q,a.t);
    }
  }
  return {a.r,p+strlen(p),a.t,a.Q,a.tag};
}

// 从a.r 读取token
// 输入 {a.r, ----, a.t, ---, -----}
// 输出 {a.r, ----, ---, a.Q, a.tag}

At getToken(At a){
  a.tag=1;
  a.Q=0;     //引用计数
  char* p=a.r;
  char* q=a.t;*q=0;
  char isN=0;
  //去空白，遇到0、（、）返回
  while(a.tag)
    switch(*p){
    case '(':a.tag+=1;
    case ')':return {p+1,a.w,a.t,a.Q,a.tag};
    case '\0':return {p,a.w,a.t,a.Q,ISNULL};
    case ' ':case '\n':case '\t':case '\r':++p;break;
    default:a.tag=0;
    }
  
  //读取引用次数
  while(*p>='0'&&*p<='9'){
    a.Q=10*(a.Q)+*p-'0';
    isN=1;
    *(q++)=*(p++);
  }
  
  //判断引号是否存在
  switch(*p){
  case '\'':
    a.Q=isN ? a.Q : 1; 
    q=a.t;
    if(*(++p)=='('){
      a.tag=ISLP;   //有引号且（ 
    } else         {
      a.tag=ISTOKEN;//有引号无（
      WAITPAIR('\'',*(q++)=*(p++));
    }
    if(*p!='\0')p++;
    break;
  default:
    a.Q=0;
    a.tag=ISTOKEN;//没有引号
    if(*p=='\"'){
      *(q++)=*(p++);
      WAITPAIR('\"',*(q++)=*(p++));
      if(*p!='\0')*(q++)=*(p++);
    }else{
      while(INSIDETOKEN)
        *(q++)=*(p++);
    }
  }
  *q='\0';
  return {p,a.w,a.t,a.Q,a.tag};
}
